package com.ruoyi.business.service.impl;

import com.ruoyi.business.domain.BuyerInfo;
import com.ruoyi.business.domain.MroLogistics;
import com.ruoyi.business.domain.OrderInfo;
import com.ruoyi.business.domain.OrderInfoDetail;
import com.ruoyi.business.mapper.BuyerInfoMapper;
import com.ruoyi.business.mapper.MroLogisticsMapper;
import com.ruoyi.business.mapper.OrderInfoDetailMapper;
import com.ruoyi.business.mapper.OrderInfoMapper;
import com.ruoyi.business.service.IOrderInfoService;
import com.ruoyi.business.utils.BadRequestException;
import com.ruoyi.business.utils.WeimobUtil;
import com.ruoyi.business.vo.*;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单管理Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderInfoServiceImpl implements IOrderInfoService {


    private final OrderInfoMapper orderInfoMapper;
    private final BuyerInfoMapper buyerInfoMapper;
    private final OrderInfoDetailMapper orderInfoDetailMapper;
    private final WeimobUtil weimobUtil;
    private final SysUserMapper sysUserMapper;
    private final MroLogisticsMapper mroLogisticsMapper;

    /**
     * 复制新增
     *
     * @param outerOrderNos 订单管理主键
     * @return 订单管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchCopyOrderInfo(List<String> outerOrderNos) {
        int count = 0;
        for (String outerOrderNo : outerOrderNos) {
            OrderInfo orderInfo = orderInfoMapper.selectOrderInfoByOuterOrderNo(outerOrderNo);
            if (orderInfo != null) {
                // 生成新的订单编号
                String newOuterOrderNo = generateNewOrderNo();

                // 复制主订单信息
                OrderInfo newOrder = new OrderInfo();
                BeanUtils.copyProperties(orderInfo, newOrder);
                newOrder.setOuterOrderNo(newOuterOrderNo);
                newOrder.setCreateTime(DateUtils.getNowDate());
                newOrder.setUpdateTime(null);
                newOrder.setUpdateBy(null);
                //支付类型 默认2
                newOrder.setPayType(2);
                newOrder.setPayTime(DateUtils.getNowDate().getTime());
                //订单支付状态 默认3
                newOrder.setOrderStatus(3);
//                newOrder.setOrderStatus(0);//3-待发货，现改成0-创建
                //渠道来源 默认 280-CPS导入订单
                newOrder.setChannelType(280);
                //2-已支付
                newOrder.setPayStatus(2);
//                newOrder.setPayStatus(0);//0-未支付；1-部分支付；2-已支付
                //1-普通订单
                newOrder.setBizSourceType(1);
                //10001-线上网店
                newOrder.setSaleChannelType(10001);
                newOrder.setOutitemId(newOuterOrderNo);
                newOrder.setVid(6017037364631L);
                newOrder.setBosName("驰选MRO");
                newOrder.setProcessVidType(2);
                newOrder.setVidType(2);
                newOrder.setProcessVidName("驰选MRO");
                //3-全款
                newOrder.setPhase(3);
                newOrder.setPaymethodIds("5");
                SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
                newOrder.setSenderName(sysUser.getNickName());
                newOrder.setCreateBy(sysUser.getNickName());
                newOrder.setSenderMobile(sysUser.getPhonenumber());
                newOrder.setProcessVid(6017037364631L);
                newOrder.setProcessVidName("驰选MRO");
                newOrder.setDeliveryType(1);
                newOrder.setStatus(1);

                // 插入新订单
                orderInfoMapper.insertOrderInfo(newOrder);

                // 复制订单详情
                List<OrderInfoDetail> details = orderInfoMapper.selectOrderInfoDetailByOuterOrderNo(outerOrderNo);
                if (details != null && !details.isEmpty()) {
                    List<OrderInfoDetail> newDetails = new ArrayList<>();
                    int id = 0;
                    for (OrderInfoDetail detail : details) {
                        OrderInfoDetail newDetail = new OrderInfoDetail();
                        BeanUtils.copyProperties(detail, newDetail);
                        //newDetail.setOutitemId(UUID.randomUUID().toString().replaceAll("-", "").substring(0, 15));
                        newDetail.setOutitemId(newOuterOrderNo + String.format("%04d", id));
                        newDetail.setOuterOrderNo(newOuterOrderNo);
                        newDetail.setCreateTime(DateUtils.getNowDate());
                        newDetail.setCreateBy(newOrder.getCreateBy());
                        newDetail.setUpdateTime(null);
                        newDetail.setUpdateBy(null);
                        newDetail.setGoodsSellMode(1);
                        newDetail.setType(1L);
                        newDetail.setDescription("商品金额");
                        newDetails.add(newDetail);
                        id++;
                    }
                    orderInfoMapper.batchOrderInfoDetail(newDetails);
                }
                count++;
            }
        }
        return count;
    }

    /**
     * 生成新的订单编号
     */
//    private String generateNewOrderNo(String originalNo) {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
//        String dateStr = sdf.format(new Date());
//        return dateStr + "-" + originalNo.substring(originalNo.length() - 4);
//    }
    public static String generateNewOrderNo() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        String timestamp = LocalDateTime.now().format(formatter);
        return "dk" + timestamp;
    }

    /**
     * 查询订单管理
     *
     * @param outerOrderNo 订单管理主键
     * @return 订单管理
     */
    @Override
    public OrderInfo selectOrderInfoByOuterOrderNo(String outerOrderNo) {
        OrderInfo orderInfo = orderInfoMapper.selectOrderInfoByOuterOrderNo(outerOrderNo);
        BuyerInfo buyerInfo = buyerInfoMapper.selectBuyerInfoByWid(orderInfo.getWid());
        orderInfo.setRemark6(buyerInfo.getName());
        return orderInfo;
    }

    /**
     * 查询订单管理列表
     *
     * @param orderInfo 订单管理
     * @return 订单管理
     */
    @Override
    public List<OrderInfo> selectOrderInfoList(OrderInfo orderInfo) {
        // 数据权限处理
        String dataScopeSql = getDataScopeSql();
        orderInfo.getParams().put("dataScope", dataScopeSql);
        return orderInfoMapper.selectOrderInfoList(orderInfo);
    }

    private String getDataScopeSql() {
        SysUser currentUser = SecurityUtils.getLoginUser().getUser();
        System.out.println("当前用户: " + currentUser.getUserName());
        for (SysRole role : currentUser.getRoles()) {
            System.out.println("角色: " + role.getRoleName() + " dataScope: " + role.getDataScope());
            if ("1".equals(role.getDataScope())) { // 管理员
                return "";
            }
        }
        return " AND create_by = '" + currentUser.getUserName() + "'";
    }


    /**
     * 新增订单管理
     *
     * @param orderInfo 订单管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertOrderInfo(OrderInfo orderInfo) {
        //新增订单
        OrderInfo newOrder = new OrderInfo();
        // 生成新的订单编号
        String newOuterOrderNo = generateNewOrderNo();
        // 主订单信息
        BeanUtils.copyProperties(orderInfo, newOrder);
        newOrder.setOuterOrderNo(newOuterOrderNo);
        newOrder.setCreateTime(DateUtils.getNowDate());
        newOrder.setUpdateTime(null);
        newOrder.setUpdateBy(null);
        //支付类型 默认2
        newOrder.setPayType(2);
        DateUtils.getNowDate();
        newOrder.setPayTime(DateUtils.getNowDate().getTime());
        //订单支付状态 默认3
        newOrder.setOrderStatus(3);
//        newOrder.setOrderStatus(0);//3-待发货，现改成0-创建
        //渠道来源 默认 280-CPS导入订单
        newOrder.setChannelType(280);
        //2-已支付
        newOrder.setPayStatus(2);
//        newOrder.setPayStatus(0);//0-未支付；2-已支付
        //1-普通订单
        newOrder.setBizSourceType(1);
        //10001-线上网店
        newOrder.setSaleChannelType(10001);
        newOrder.setOutitemId(newOuterOrderNo);
        newOrder.setVid(6017037364631L);
        newOrder.setBosName("驰选MRO");
        newOrder.setProcessVidType(2);
        newOrder.setVidType(2);
        newOrder.setProcessVidName("驰选MRO");
        //3-全款
        newOrder.setPhase(3);
        newOrder.setPaymethodIds("5");
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        newOrder.setSenderName(sysUser.getNickName());
        newOrder.setSenderMobile(sysUser.getPhonenumber());
        newOrder.setCreateBy(sysUser.getNickName());
        newOrder.setProcessVid(6017037364631L);
        newOrder.setProcessVidName("驰选MRO");
        newOrder.setDeliveryType(1);
        newOrder.setStatus(1);
        // 插入新订单
        orderInfoMapper.insertOrderInfo(newOrder);

        // 订单详情
        List<OrderInfoDetail> orderInfoDetailList = orderInfo.getOrderInfoDetailList();
        if (StringUtils.isNotNull(orderInfoDetailList)) {
            List<OrderInfoDetail> list = new ArrayList<OrderInfoDetail>();
            int id = 0;
            for (OrderInfoDetail orderInfoDetail : orderInfoDetailList) {
                orderInfoDetail.setOuterOrderNo(newOuterOrderNo);
               // orderInfoDetail.setOutitemId(UUID.randomUUID().toString().replaceAll("-", "").substring(0, 15));
                orderInfoDetail.setOutitemId(newOuterOrderNo + String.format("%04d", id));

                orderInfoDetail.setCreateTime(DateUtils.getNowDate());
                orderInfoDetail.setCreateBy(newOrder.getCreateBy());
                orderInfoDetail.setUpdateTime(null);
                orderInfoDetail.setUpdateBy(null);
                orderInfoDetail.setGoodsSellMode(1);
                orderInfoDetail.setType(1L);
                orderInfoDetail.setDescription("商品金额");
                // 验证商品明细
                if (orderInfoDetail.getSalePrice() == null || orderInfoDetail.getSalePrice().compareTo(BigDecimal.ZERO) <= 0) {
                    throw new RuntimeException("商品价格必须大于0");
                }
                if (orderInfoDetail.getSkuNum() == null || orderInfoDetail.getSkuNum() <= 0) {
                    throw new RuntimeException("商品数量必须大于0");
                }
                //金额计算
                BigDecimal salePrice = orderInfoDetail.getSalePrice();
                BigDecimal skuNum = BigDecimal.valueOf(orderInfoDetail.getSkuNum());
                BigDecimal awt = salePrice.multiply(skuNum);
                BigDecimal roundedResult = awt.setScale(2, RoundingMode.HALF_UP);
                //计算原金额 原单价*数量=原金额
                BigDecimal unitPrice = orderInfoDetail.getUnitPrice();
                BigDecimal unAmt = unitPrice.multiply(skuNum);
                BigDecimal unitAmount = unAmt.setScale(2, RoundingMode.HALF_UP);
                orderInfoDetail.setUnitAmount(unitAmount);
                //商品金额
                orderInfoDetail.setAmount(roundedResult);
                //总金额
                orderInfoDetail.setTotalAmount(roundedResult);
                //有抹零金额则相加
                BigDecimal zeroAmount = orderInfoDetail.getZeroAmount();
                if (zeroAmount.compareTo(BigDecimal.ZERO) > 0) {
                    zeroAmount = zeroAmount.negate();
                    orderInfoDetail.setPayAmount(roundedResult.add(zeroAmount));
                    orderInfoDetail.setShouldPayAmount(roundedResult.add(zeroAmount));
                }else {
                    //实付金额 +抹零金额
                    orderInfoDetail.setPayAmount(roundedResult);
                    //应付金额+抹零金额
                    orderInfoDetail.setShouldPayAmount(roundedResult);
                }
                list.add(orderInfoDetail);
                id++;
            }
            if (list.size() > 0) {
                orderInfoMapper.batchOrderInfoDetail(list);
            }
        }

        //更新主表金额和数量
        orderInfoMapper.updatePayAmt(newOuterOrderNo);
        //查询金额 更新积分
        OrderInfo orderInfo1 = orderInfoMapper.selectOrderInfoByOuterOrderNo(newOuterOrderNo);
        /*if (orderInfo1.getRemark3().compareTo(orderInfo1.getShouldPayAmount())>=0){
            //原金额大于应付 少开 取应付金额
            BigDecimal or = orderInfo1.getShouldPayAmount();
            //需要严格的截断（即去掉小数部分）
            BigDecimal strictTruncate = or.setScale(0, RoundingMode.FLOOR);
            if (strictTruncate.compareTo(new BigDecimal(0))>0){
                orderInfo1.setRemark2(strictTruncate.toString());
            }else {
                //小于1
                orderInfo1.setRemark2(" ");
            }
        }else {
            //多开取原金额
            BigDecimal or = orderInfo1.getRemark3();
            //需要严格的截断（即去掉小数部分）
            BigDecimal strictTruncate = or.setScale(0, RoundingMode.FLOOR);
            if (strictTruncate.compareTo(new BigDecimal(0))>0){
                orderInfo1.setRemark2(strictTruncate.toString());
            }else {
                //小于1
                orderInfo1.setRemark2(" ");
            }
        }*/
        // fixme  修改为：无论多开少开，积分全部取实际支付金额
        BigDecimal or = orderInfo1.getShouldPayAmount();
        //需要严格的截断（即去掉小数部分）
        BigDecimal strictTruncate = or.setScale(0, RoundingMode.HALF_UP);
        if (strictTruncate.compareTo(new BigDecimal(0))>0){
            orderInfo1.setRemark2(strictTruncate.toString());
        }else {
            //小于1
            orderInfo1.setRemark2(" ");
        }
        //更新主表金额和数量
        orderInfoMapper.updatePayAmt2(orderInfo1);
        int rows = 1;
        return rows;
    }

    /**
     * 修改订单管理
     *
     * @param orderInfo 订单管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateOrderInfo(OrderInfo orderInfo) {
        // 检查订单状态是否为1
        OrderInfo existingOrder = orderInfoMapper.selectOrderInfoByOuterOrderNo(orderInfo.getOuterOrderNo());
        if (existingOrder == null) {
            throw new RuntimeException("订单不存在: " + orderInfo.getOuterOrderNo());
        }
        if (existingOrder.getStatus() != 1 ) {
            throw new RuntimeException("订单状态不是【草稿】状态，无法修改！");
        }
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        if( !sysUser.getNickName().equals(existingOrder.getCreateBy())  ){
            throw new RuntimeException("当前登录人不是创建人，不能修改！");
        }
        orderInfo.setUpdateBy(sysUser.getNickName());
        orderInfo.setUpdateTime(DateUtils.getNowDate());
        orderInfoMapper.deleteOrderInfoDetailByOutitemId(orderInfo.getOuterOrderNo());
        insertOrderInfoDetail(orderInfo);
        //更新主表金额和数量
        orderInfoMapper.updateOrderInfo(orderInfo);
        orderInfoMapper.updatePayAmt(orderInfo.getOuterOrderNo());
        //查询金额 更新积分
        OrderInfo orderInfo1 = orderInfoMapper.selectOrderInfoByOuterOrderNo(orderInfo.getOuterOrderNo());
        /*if (orderInfo1.getRemark3().compareTo(orderInfo1.getShouldPayAmount())>=0){
            //原金额大于应付 少开 取应付金额
            BigDecimal or = orderInfo1.getShouldPayAmount();
            //需要严格的截断（即去掉小数部分）
            BigDecimal strictTruncate = or.setScale(0, RoundingMode.FLOOR);
            if (strictTruncate.compareTo(new BigDecimal(0))>0){
                orderInfo1.setRemark2(strictTruncate.toString());
            }else {
                //小于1
                orderInfo1.setRemark2(" ");
            }
        }else {
            //多开取原金额
            BigDecimal or = orderInfo1.getRemark3();
            //需要严格的截断（即去掉小数部分）
            BigDecimal strictTruncate = or.setScale(0, RoundingMode.FLOOR);
            if (strictTruncate.compareTo(new BigDecimal(0))>0){
                orderInfo1.setRemark2(strictTruncate.toString());
            }else {
                //小于1
                orderInfo1.setRemark2(" ");
            }
        }*/
        // fixme  修改为：无论多开少开，积分全部取实际支付金额
        BigDecimal or = orderInfo1.getShouldPayAmount();
        //需要严格的截断（即去掉小数部分）
        BigDecimal strictTruncate = or.setScale(0, RoundingMode.HALF_UP);
        if (strictTruncate.compareTo(new BigDecimal(0))>0){
            orderInfo1.setRemark2(strictTruncate.toString());
        }else {
            //小于1
            orderInfo1.setRemark2(" ");
        }
        //更新主表金额和数量
        return orderInfoMapper.updatePayAmt2(orderInfo1);
    }

    /**
     * 批量删除订单管理
     *
     * @param outerOrderNos 需要删除的订单管理主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteOrderInfoByOuterOrderNos(String[] outerOrderNos) {
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        String nickName = sysUser.getNickName();
        // 检查所有订单状态是否为1
        for (String outerOrderNo : outerOrderNos) {
            OrderInfo orderInfo = orderInfoMapper.selectOrderInfoByOuterOrderNo(outerOrderNo);
            if (orderInfo == null) {
                throw new RuntimeException("订单不存在: " + outerOrderNo);
            }
            if (orderInfo.getStatus() != 1 && orderInfo.getStatus() != 5) {
                throw new RuntimeException("订单 " + outerOrderNo + " 状态不是【草稿】或【作废】，无法删除！");
            }
            if(!orderInfo.getCreateBy().equals(nickName ) ){
                throw new RuntimeException("当前登录人不是创建人，不能删除！");
            }
            orderInfoMapper.updateRestoreStatus(outerOrderNo, orderInfo.getStatus());
        }
        //改为逻辑删除:(1)order_info_detail表的status 0：正常，1：已删除（2）order_info表的status 5作废6删除
        //orderInfoMapper.deleteOrderInfoDetailByOutitemIds(outerOrderNos);
        //return orderInfoMapper.deleteOrderInfoByOuterOrderNos(outerOrderNos);
        orderInfoDetailMapper.updateOrderInfoDetailByOutitemIds(nickName, Arrays.asList(outerOrderNos));
        return orderInfoMapper.updateOrderInfoByOuterOrderNos(nickName, Arrays.asList(outerOrderNos));
    }

    /**
     * 删除订单管理信息
     *
     * @param outerOrderNo 订单管理主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteOrderInfoByOuterOrderNo(String outerOrderNo) {
        // 检查订单状态是否为1
        OrderInfo orderInfo = orderInfoMapper.selectOrderInfoByOuterOrderNo(outerOrderNo);
        if (orderInfo == null) {
            throw new RuntimeException("订单不存在: " + outerOrderNo);
        }
        if (orderInfo.getStatus() != 1 && orderInfo.getStatus() != 5) {
            throw new RuntimeException("订单状态不是【草稿】或【作废】，无法删除");
        }
        //改为逻辑删除:(1)order_info_detail表的status 0：正常，1：已删除（2）order_info表的status 5作废6删除
        //orderInfoMapper.deleteOrderInfoDetailByOutitemId(outerOrderNo);
        //return orderInfoMapper.deleteOrderInfoByOuterOrderNo(outerOrderNo);
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        String nickName = sysUser.getNickName();
        orderInfoDetailMapper.updateOrderInfoDetailByOutitemId(nickName, outerOrderNo);
        return orderInfoMapper.updateOrderInfoByOuterOrderNo(nickName, outerOrderNo);
    }

    /**
     * 新增订单详情商品信息
     *
     * @param orderInfo 订单管理对象
     */
    public void insertOrderInfoDetail(OrderInfo orderInfo) {
        List<OrderInfoDetail> orderInfoDetailList = orderInfo.getOrderInfoDetailList();
        String outerOrderNo = orderInfo.getOuterOrderNo();
        int id = 0;
        if (StringUtils.isNotNull(orderInfoDetailList)) {
            List<OrderInfoDetail> list = new ArrayList<OrderInfoDetail>();
            for (OrderInfoDetail orderInfoDetail : orderInfoDetailList) {
                orderInfoDetail.setOuterOrderNo(outerOrderNo);
                orderInfoDetail.setGoodsSellMode(1);
                //orderInfoDetail.setOutitemId(UUID.randomUUID().toString().replaceAll("-", "").substring(0, 15));
                orderInfoDetail.setOutitemId(outerOrderNo + String.format("%04d", id));
                // 验证商品明细
                if (orderInfoDetail.getSalePrice() == null || orderInfoDetail.getSalePrice().compareTo(BigDecimal.ZERO) <= 0) {
                    throw new RuntimeException("商品价格必须大于0");
                }
                if (orderInfoDetail.getSkuNum() == null || orderInfoDetail.getSkuNum() <= 0) {
                    throw new RuntimeException("商品数量必须大于0");
                }
                //金额计算
                BigDecimal salePrice = orderInfoDetail.getSalePrice();
                BigDecimal skuNum = BigDecimal.valueOf(orderInfoDetail.getSkuNum());
                BigDecimal awt = salePrice.multiply(skuNum);
                BigDecimal roundedResult = awt.setScale(2, RoundingMode.HALF_UP);
                orderInfoDetail.setAmount(roundedResult);
                orderInfoDetail.setTotalAmount(roundedResult);

                //计算原金额 原单价*数量=原金额
                BigDecimal unitPrice = orderInfoDetail.getUnitPrice();
                BigDecimal unAmt = unitPrice.multiply(skuNum);
                BigDecimal unitAmount = unAmt.setScale(2, RoundingMode.HALF_UP);
                orderInfoDetail.setUnitAmount(unitAmount);

                //有抹零金额则相加
                BigDecimal zeroAmount = orderInfoDetail.getZeroAmount();
                if (zeroAmount.compareTo(BigDecimal.ZERO) > 0) {
                    zeroAmount = zeroAmount.negate();
                    //实付金额 +抹零金额
                    orderInfoDetail.setPayAmount(roundedResult.add(zeroAmount));
                    orderInfoDetail.setShouldPayAmount(roundedResult.add(zeroAmount));
                }else {
                    //实付金额
                    orderInfoDetail.setPayAmount(roundedResult);
                    //应付金额
                    orderInfoDetail.setShouldPayAmount(roundedResult);
                }
                list.add(orderInfoDetail);
                id++;
            }
            if (list.size() > 0) {
                orderInfoMapper.batchOrderInfoDetail(list);
            }
        }
    }

    @Override
    public void sendOrderInfo(List<String> outerOrderNos) {
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        String nickName = sysUser.getNickName();
        if (CollectionUtils.isEmpty(outerOrderNos)) {
            throw new BadRequestException("订单编号不能为空！");
        }
        List<OrderInfo> orderInfoList = orderInfoMapper.selectOrderInfoByOuterOrderNos(outerOrderNos);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应数据");
        }
        orderInfoList.forEach(item -> {
            if (item.getStatus() != 1) {
                throw new BadRequestException("订单编号为：" + item.getOuterOrderNo() + "的状态非【草稿】,请勿勾选！");
            }
            if(!item.getCreateBy().equals(nickName ) ){
                throw new RuntimeException("订单编号为：" + item.getOuterOrderNo() + "当前登录人不是创建人，不能操作！");
            }
        });
        for (OrderInfo target : orderInfoList) {
            sendSingleOrder(target, nickName);
        }
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void sendSingleOrder(OrderInfo target, String nickName) {
        BuyerInfo targetBuyerInfo = buyerInfoMapper.selectBuyerInfoByWid(target.getWid());
        if (ObjectUtils.isEmpty(targetBuyerInfo)) {
            throw new BadRequestException("客户编号为：" + target.getWid() + "找不到对应数据");
        }
        // 构建请求对象
        SendOrderInfoVo sendOrderInfoVo = getSendOrderInfoVo(target, targetBuyerInfo);
        // 调用微盟外部订单导入
        boolean success = weimobUtil.sendOrderInfoToWeimob(sendOrderInfoVo);

        Long orderNo = null;
        int retries = 0;
        int maxRetries = 5; // 最多尝试 5 次
        int waitMillis = 2000; // 每次等待 2 秒
        while (retries < maxRetries) {
            // 获取微盟订单编号
            Long createTime = target.getCreateTime().getTime();
            LocalDateTime ldt = Instant.ofEpochMilli(createTime)
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            LocalDateTime startOfDay = ldt.toLocalDate().atStartOfDay();
            LocalDateTime startOfNextDay = startOfDay.plusDays(1);
            long start = startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            long end = startOfNextDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

            orderNo = this.searchOrderInfoFromWeimob(target.getOuterOrderNo(), start, end);
            if (!ObjectUtils.isEmpty(orderNo)) {
                break; // 成功获取到订单编号，跳出循环
            }
            retries++;
            try {
                Thread.sleep(waitMillis);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("线程被中断", e);
            }
        }
        if (ObjectUtils.isEmpty(orderNo)) {
            throw new BadRequestException("发送成功，但获取微盟订单编号失败！");
        }
        // 更新订单状态和微盟订单编号
        orderInfoMapper.updateOrderNo(target.getOuterOrderNo(), 2, orderNo, nickName);
    }


    /**
     * @param target          订单信息
     * @param targetBuyerInfo
     * @return
     */
    private SendOrderInfoVo getSendOrderInfoVo(OrderInfo target, BuyerInfo targetBuyerInfo) {
        SendOrderInfoVo sendOrderInfoVo = new SendOrderInfoVo();
        //买家信息
        BuyerInfo buyerInfo = new BuyerInfo();
        buyerInfo.setBuyerRemark(target.getRemark());
        buyerInfo.setWid(target.getWid());
        buyerInfo.setPhone(targetBuyerInfo.getPhone());
        buyerInfo.setUserNickName(targetBuyerInfo.getName());
        sendOrderInfoVo.setBuyerInfo(buyerInfo);

        //配送信息
        SendOrderInfoVo.DeliveryInfo deliveryInfo = new SendOrderInfoVo.DeliveryInfo();
        //发送方
        SendOrderInfoVo.SendInfo sendInfo = new SendOrderInfoVo.SendInfo();
        SendOrderInfoVo.SenderInfo senderInfo = new SendOrderInfoVo.SenderInfo();
        senderInfo.setSenderName(target.getSenderName());
        senderInfo.setSenderMobile(target.getSenderMobile());
        sendInfo.setSenderInfo(senderInfo);
        sendInfo.setProcessVid(target.getProcessVid());
        sendInfo.setProcessVidName(target.getProcessVidName());
        //收货方信息
        SendOrderInfoVo.ReceiveInfo receiveInfo = new SendOrderInfoVo.ReceiveInfo();
        SendOrderInfoVo.AddressInfo addressInfo = new SendOrderInfoVo.AddressInfo();
        addressInfo.setAddress(target.getAddress());
        addressInfo.setProvince(target.getProvince());
        addressInfo.setCity(target.getCity());
        addressInfo.setCounty(target.getCounty());
        receiveInfo.setAddressInfo(addressInfo);

        SendOrderInfoVo.ReceiverInfo receiverInfo = new SendOrderInfoVo.ReceiverInfo();
        receiverInfo.setReceiverName(target.getReceiverName());
        receiverInfo.setReceiverMobile(target.getReceiverMobile());
        receiveInfo.setReceiverInfo(receiverInfo);

        deliveryInfo.setSendInfo(sendInfo);
        deliveryInfo.setDeliveryType(target.getDeliveryType());
        deliveryInfo.setReceiveInfo(receiveInfo);
        sendOrderInfoVo.setDeliveryInfo(deliveryInfo);

        //订单基本信息
        SendOrderInfoVo.OrderBaseInfo orderBaseInfo = new SendOrderInfoVo.OrderBaseInfo();
        List<SendOrderInfoVo.TimeItem> timeList = new ArrayList<>();
        //101-订单创建时间,102-支付完成时间,103-可发货时间
        long currentTimeMillis = System.currentTimeMillis();
        timeList.add(new SendOrderInfoVo.TimeItem(101, currentTimeMillis));
        timeList.add(new SendOrderInfoVo.TimeItem(102, currentTimeMillis));
        timeList.add(new SendOrderInfoVo.TimeItem(103, currentTimeMillis));
        orderBaseInfo.setTimeList(timeList);
        orderBaseInfo.setPayType(target.getPayType());
        orderBaseInfo.setPayTime(currentTimeMillis);
        orderBaseInfo.setOrderStatus(target.getOrderStatus());
        orderBaseInfo.setChannelType(target.getChannelType());
        orderBaseInfo.setOuterOrderNo(target.getOuterOrderNo());
        orderBaseInfo.setPayStatus(target.getPayStatus());
        orderBaseInfo.setBizSourceType(target.getBizSourceType());
        orderBaseInfo.setSaleChannelType(target.getSaleChannelType());
        sendOrderInfoVo.setOrderBaseInfo(orderBaseInfo);


        ArrayList<SendOrderInfoVo.ItemInfo> itemInfoList = new ArrayList<>();
        List<OrderInfoDetail> orderInfoDetails = orderInfoMapper.selectOrderInfoDetailByOuterOrderNo(target.getOuterOrderNo());
        orderInfoDetails.forEach(item -> {
            //订单明细
            SendOrderInfoVo.ItemInfo itemInfo = new SendOrderInfoVo.ItemInfo();
            itemInfo.setOutItemId(item.getOutitemId());

            SendOrderInfoVo.PayInfo payInfo = new SendOrderInfoVo.PayInfo();
            payInfo.setTotalAmount(String.valueOf(item.getTotalAmount()));
            payInfo.setShouldPayAmount(String.valueOf(item.getShouldPayAmount()));
            payInfo.setPayAmount(String.valueOf(item.getPayAmount()));
            itemInfo.setPayInfo(payInfo);

            SendOrderInfoVo.GoodsInfo goodsInfo = new SendOrderInfoVo.GoodsInfo();
            goodsInfo.setSalePrice(String.valueOf(item.getSalePrice()));
            goodsInfo.setGoodsSellMode(item.getGoodsSellMode());
            goodsInfo.setSkuId(item.getSkuId());
            goodsInfo.setSkuNum(String.valueOf(item.getSkuNum()));
            goodsInfo.setSkuCode(item.getSkuCode());
            goodsInfo.setCategoryId(item.getCategoryId());
            itemInfo.setGoodsInfo(goodsInfo);

            ArrayList<SendOrderInfoVo.DiscountInfo > discountInfoList = new ArrayList<>();
            SendOrderInfoVo.DiscountInfo discountInfo = new SendOrderInfoVo.DiscountInfo();
            //0-商品级；1-运费；2-订单级；
            discountInfo.setDiscountLevel(0);
            discountInfo.setDiscountExt(new SendOrderInfoVo.DiscountExt("1",1));
            discountInfo.setDiscountAmount(String.valueOf(item.getZeroAmount()));
            //29-抹零
            discountInfo.setDiscountType(29);

            discountInfoList.add(discountInfo);
            itemInfo.setDiscountInfoList(discountInfoList);

            itemInfoList.add(itemInfo);
        });
        sendOrderInfoVo.setItemInfoList(itemInfoList);

        //商家信息
        SendOrderInfoVo.MerchantInfo merchantInfo = new SendOrderInfoVo.MerchantInfo();
        merchantInfo.setVid(target.getVid());
        merchantInfo.setBosName(target.getBosName());
        merchantInfo.setProcessVidType(target.getProcessVidType());
        merchantInfo.setProcessVid(target.getProcessVid());
        merchantInfo.setVidType(target.getVidType());
        merchantInfo.setProcessVidName(target.getProcessVidName());
        sendOrderInfoVo.setMerchantInfo(merchantInfo);

        //支付明细信息
        SendOrderInfoVo.PaymentDetail paymentDetail = new SendOrderInfoVo.PaymentDetail();
        paymentDetail.setPhase(target.getPhase());
        paymentDetail.setPayTime(currentTimeMillis);
        paymentDetail.setPayMethodIds(Arrays.stream(target.getPaymethodIds().split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .map(Integer::valueOf)
                .collect(Collectors.toList()));
        sendOrderInfoVo.setPaymentDetails(Collections.singletonList(paymentDetail));

        // 支付信息
        // 订单详情添加抹零，订单级也要跟着减少
        SendOrderInfoVo.PayInfo payInfo = new SendOrderInfoVo.PayInfo();
        payInfo.setTotalAmount(String.valueOf(target.getTotalAmount()));
        payInfo.setShouldPayAmount(String.valueOf(target.getShouldPayAmount()));
        payInfo.setPayAmount(String.valueOf(target.getPayAmount()));
        sendOrderInfoVo.setPayInfo(payInfo);
        return sendOrderInfoVo;
    }


    /**
     * 默认的发送方数据
     *
     * @return
     */
    public static SendLogisticsVo.SendInfo getDefaultSendInfo() {
        SendLogisticsVo.SendInfo sendInfo = new SendLogisticsVo.SendInfo();
        sendInfo.setSenderAddress("湖北省荆门市京山市屈场路领工防护装备有限公司");
        sendInfo.setProcessVid(6017037364631L);
        sendInfo.setProcessVidName("驰选MRO");

        SendLogisticsVo.AddressInfo addressInfo = new SendLogisticsVo.AddressInfo();
        addressInfo.setArea("屈场路");
        addressInfo.setZip("0");
        addressInfo.setAddress("湖北省荆门市京山市屈场路领工防护装备有限公司");
        addressInfo.setProvince("湖北省");
        addressInfo.setCity("荆门市");
        addressInfo.setCounty("京山市");
        addressInfo.setLatitude("0");
        addressInfo.setLongitude("0");
        SendLogisticsVo.AddressExt addressExt = new SendLogisticsVo.AddressExt();
        addressExt.setAreaCode("0");
        addressExt.setCountyCode("0");
        addressExt.setCityCode("0");
        addressExt.setProvinceCode("0");
        addressInfo.setAddressExt(addressExt);
        sendInfo.setAddressInfo(addressInfo);

        SendLogisticsVo.SenderInfo senderInfo = new SendLogisticsVo.SenderInfo();
        senderInfo.setSenderName("邓敏");
        senderInfo.setSenderMobile("15827876803");
        sendInfo.setSenderInfo(senderInfo);

        return sendInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendLogistics(List<String> outerOrderNos) {
        if (CollectionUtils.isEmpty(outerOrderNos)) {
            throw new BadRequestException("订单编号不能为空！");
        }
        //判断订单状态
        List<OrderInfo> orderInfoList = orderInfoMapper.selectOrderInfoByOuterOrderNos(outerOrderNos);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应订单数据");
        }
        orderInfoList.forEach(item -> {
            if (item.getStatus() != 2) {
                throw new BadRequestException("订单编号为：" + item.getOuterOrderNo() + "的状态非 生效已发送,请勿勾选！");
            }
        });

        //判断订单的物流是否存在 & 物流状态
        List<MroLogistics> mroLogistics = mroLogisticsMapper.selectMroLogisticsByOuterOrderNo(outerOrderNos);
        if (CollectionUtils.isEmpty(mroLogistics)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应物流数据");
        }
        mroLogistics.forEach(item -> {
            if (item.getStatus() != 0) {
                throw new BadRequestException("订单编号为：" + item.getOuterOrderNo() + "物流编号为" + item.getNumber() + "的物流状态 不是草稿,请勿勾选！");
            }
        });

        Map<String, Long> createTimeMap = orderInfoList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getCreateTime().getTime()
                ));
        /*Map<String, BigDecimal> payAmountMap = orderInfoList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getPayAmount()
                ));*/
        Map<String, List<MroLogistics>> mroLogisticMap = mroLogistics.stream()
                .collect(Collectors.groupingBy(MroLogistics::getOuterOrderNo));
        
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        String nickName = null;
        if(sysUser!=null){
            nickName= sysUser.getNickName();
        }

        //订单
        for (Map.Entry<String, List<MroLogistics>> entry : mroLogisticMap.entrySet()) {
            String outerOrderNo = entry.getKey();

            // 1、获取微盟订单编号
            //调用微盟 查询订单列表接口：通过创建时间和外部订单编号 -> 获取微盟订单编号
            /*Long createTime = createTimeMap.get(outerOrderNo);
            LocalDateTime ldt = Instant.ofEpochMilli(createTime)
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            // 当天 00:00:00
            LocalDateTime startOfDay = ldt.toLocalDate().atStartOfDay();
            // 次日 00:00:00
            LocalDateTime startOfNextDay = startOfDay.plusDays(1);
            // 转回时间戳
            long start = startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            long end = startOfNextDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

            Long orderNo = this.searchOrderInfoFromWeimob(outerOrderNo, start, end);
            orderInfoMapper.updateOrderNo(outerOrderNo, 2,orderNo,nickName);*/

            //2、调用微盟 外部订单更新：推送支付信息
           /* UpdateOrderPayInfoVo updateOrderPayInfoVo = new UpdateOrderPayInfoVo();
            updateOrderPayInfoVo.setOrderNo(orderNo);
            updateOrderPayInfoVo.setOrderStatus(2);

            List<UpdateOrderPayInfoVo.OrderTimeInfo> payOrderTimeInfo = new ArrayList<>();
            //101-订单创建时间；102-支付完成时间；
            payOrderTimeInfo.add(new UpdateOrderPayInfoVo.OrderTimeInfo(101, createTime));
            long currentTimeMillisPay = System.currentTimeMillis();
            payOrderTimeInfo.add(new UpdateOrderPayInfoVo.OrderTimeInfo(102, currentTimeMillisPay));
            updateOrderPayInfoVo.setOrderTimeInfos(payOrderTimeInfo);

            ArrayList<UpdateOrderPayInfoVo.PayFinishInfo> payFinishInfos = new ArrayList<>();
            UpdateOrderPayInfoVo.PayFinishInfo payFinishInfo = new UpdateOrderPayInfoVo.PayFinishInfo();
            payFinishInfo.setChannelTrxNo(String.valueOf(currentTimeMillisPay));
            BigDecimal payAmount = payAmountMap.get(outerOrderNo);
            payFinishInfo.setPayAmount(String.valueOf(payAmount));
            payFinishInfo.setPayMethod(5);
            payFinishInfo.setPayTime(currentTimeMillisPay);
            payFinishInfos.add(payFinishInfo);
            updateOrderPayInfoVo.setPayFinishInfos(payFinishInfos);
            weimobUtil.sendPayInfoToWeimob(updateOrderPayInfoVo);*/

            //3、调用微盟 外部订单更新：推送物流信息
            SendLogisticsVo sendLogisticsVo = new SendLogisticsVo();
            sendLogisticsVo.setOrderNo(entry.getValue().get(0).getOrderNo());
            sendLogisticsVo.setOrderStatus(5);//已发货

            List<SendLogisticsVo.OrderTimeInfo> orderTimeInfos = new ArrayList<>();
            //101-订单创建时间；102-支付完成时间；103-可发货时间；104-订单首次发货时间；105-发货完成时间；106-确认收货时间；107-订单完成时间；108-订单取消时间
            orderTimeInfos.add(new SendLogisticsVo.OrderTimeInfo(101, createTimeMap.get(outerOrderNo)));
            orderTimeInfos.add(new SendLogisticsVo.OrderTimeInfo(102, createTimeMap.get(outerOrderNo)));
            orderTimeInfos.add(new SendLogisticsVo.OrderTimeInfo(103, createTimeMap.get(outerOrderNo)));
            long currentTimeMillis = System.currentTimeMillis();
            orderTimeInfos.add(new SendLogisticsVo.OrderTimeInfo(104, currentTimeMillis));
            orderTimeInfos.add(new SendLogisticsVo.OrderTimeInfo(105, currentTimeMillis));
            sendLogisticsVo.setOrderTimeInfos(orderTimeInfos);

            List<SendLogisticsVo.PackageInfo> packageList = new ArrayList<>();
            List<MroLogistics> logisticsList = entry.getValue();
            //物流
            for (MroLogistics logistics : logisticsList) {

                SendLogisticsVo.PackageInfo packageInfo = new SendLogisticsVo.PackageInfo();
                packageInfo.setDeliveryTime(currentTimeMillis);
                packageInfo.setDeliveryMethod(1);//发货方式:1-快递物流


                List<SendLogisticsVo.PackageItem> packageItems = new ArrayList<>();
                //商品项
                List<String> outItemIdList = Arrays.asList(logistics.getOutItemId().split(","));
                List<String> skuNumList = Arrays.asList(logistics.getSkuNum().split(","));
                for (int i = 0; i < outItemIdList.size(); i++) {
                    packageItems.add(new SendLogisticsVo.PackageItem(outItemIdList.get(i), skuNumList.get(i)));
                }
                packageInfo.setPackageItems(packageItems);


                SendLogisticsVo.SendInfo defaultSendInfo = getDefaultSendInfo();
                packageInfo.setSendInfo(defaultSendInfo);

                SendLogisticsVo.DeliveryImportInfo deliveryImportInfo = new SendLogisticsVo.DeliveryImportInfo();
                deliveryImportInfo.setCompanyCode(logistics.getCompanyCode());
                deliveryImportInfo.setNumber(logistics.getNumber());
                deliveryImportInfo.setCompanyName(logistics.getCompanyName());
                deliveryImportInfo.setExpectReceivedType(5);//5-尽快送达
                deliveryImportInfo.setExpectReceivedStartTime(currentTimeMillis);
                deliveryImportInfo.setExpectReceivedEndTime(currentTimeMillis);
                deliveryImportInfo.setExpectReceivedDate(currentTimeMillis);
                packageInfo.setDeliveryImportInfo(deliveryImportInfo);

                SendLogisticsVo.ReceiveInfo receiveInfo = new SendLogisticsVo.ReceiveInfo();
                receiveInfo.setReceiverAddress(logistics.getReceiverAddress());
                SendLogisticsVo.AddressInfo addressInfo = new SendLogisticsVo.AddressInfo();
                addressInfo.setArea(logistics.getArea());
                addressInfo.setZip(logistics.getZip());
                addressInfo.setAddress(logistics.getAddress());
                addressInfo.setProvince(logistics.getProvince());
                addressInfo.setCity(logistics.getCity());
                addressInfo.setCounty(logistics.getCounty());
                addressInfo.setLatitude(logistics.getLatitude());
                addressInfo.setLongitude(logistics.getLongitude());

                SendLogisticsVo.AddressExt addressExt = new SendLogisticsVo.AddressExt();
                addressExt.setAreaCode(logistics.getAreaCode());
                addressExt.setCountyCode(logistics.getCountyCode());
                addressExt.setCityCode(logistics.getCityCode());
                addressExt.setProvinceCode(logistics.getProvinceCode());
                receiveInfo.setAddressInfo(addressInfo);

                SendLogisticsVo.ReceiverInfo receiverInfo = new SendLogisticsVo.ReceiverInfo();
                receiverInfo.setReceiverName(logistics.getReceiverName());
                receiverInfo.setReceiverMobile(logistics.getReceiverMobile());
                receiveInfo.setReceiverInfo(receiverInfo);
                packageInfo.setReceiveInfo(receiveInfo);

                packageList.add(packageInfo);
            }
            sendLogisticsVo.setPackageList(packageList);

            //调用微盟 外部订单更新
            boolean success = weimobUtil.sendMroLogisticsToWeimob(sendLogisticsVo);
            //成功，更新物流状态：1已发货   更新订单状态：3已发货
            if (success) {
                orderInfoMapper.updateOrderStatus(outerOrderNo, 3,nickName);
                List<String> deliveryNoList = logisticsList.stream()
                        .map(MroLogistics::getDeliveryNo)
                        .collect(Collectors.toList());
                mroLogisticsMapper.bitchUpdateMroLogisticsStatus(deliveryNoList, 1,nickName);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendFinishStatus(List<String> outerOrderNos) {
        if (CollectionUtils.isEmpty(outerOrderNos)) {
            throw new BadRequestException("订单编号不能为空！");
        }
        //判断订单状态
        List<OrderInfo> orderInfoList = orderInfoMapper.selectOrderInfoByOuterOrderNos(outerOrderNos);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应订单数据");
        }
        orderInfoList.forEach(item -> {
            if (item.getStatus() != 3) {
                throw new BadRequestException("订单编号为：" + item.getOuterOrderNo() + "的状态非 已发货,请勿勾选！");
            }
        });

        //判断订单的 物流状态
        List<MroLogistics> mroLogistics = mroLogisticsMapper.selectMroLogisticsByOuterOrderNo(outerOrderNos);
        if (CollectionUtils.isEmpty(mroLogistics)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应物流数据");
        }
        mroLogistics.forEach(item -> {
            if (item.getStatus() != 1) {
                throw new BadRequestException("订单编号为：" + item.getOuterOrderNo() + "物流编号为" + item.getNumber() + "的物流状态非 已发货,请勿勾选！");
            }
        });


        Map<String, Long> createTimeMap = orderInfoList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getCreateTime().getTime()
                ));
        Map<String, List<MroLogistics>> mroLogisticMap = mroLogistics.stream()
                .collect(Collectors.groupingBy(MroLogistics::getOuterOrderNo));

        for (OrderInfo orderInfo : orderInfoList) {
            SendFinishStatusVo sendFinishStatusVo = new SendFinishStatusVo();
            String outerOrderNo = orderInfo.getOuterOrderNo();
            Long orderNo = mroLogisticMap.get(outerOrderNo).get(0).getOrderNo();
            sendFinishStatusVo.setOrderNo(orderNo);
            sendFinishStatusVo.setOrderStatus(8);//完成

            List<SendFinishStatusVo.OrderTimeInfo> orderTimeInfos = new ArrayList<>();
            //101-订单创建时间；102-支付完成时间；103-可发货时间；104-订单首次发货时间；105-发货完成时间；106-确认收货时间；107-订单完成时间；108-订单取消时间
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(101, createTimeMap.get(outerOrderNo)));
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(102, createTimeMap.get(outerOrderNo)));
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(103, createTimeMap.get(outerOrderNo)));
            long currentTimeMillis = System.currentTimeMillis();
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(104, currentTimeMillis));
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(105, currentTimeMillis));
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(106, currentTimeMillis));
            orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(107, currentTimeMillis));
            sendFinishStatusVo.setOrderTimeInfos(orderTimeInfos);

            //调用微盟 外部订单更新
            boolean success = weimobUtil.sendFinishStatusToWeimob(sendFinishStatusVo);
            //成功，更新物流状态：2已完成   更新订单状态：4完成
            if (success) {
                SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
                String nickName = sysUser.getNickName();
                orderInfoMapper.updateOrderStatus(outerOrderNo, 4,nickName);
                List<MroLogistics> logisticsList = mroLogisticMap.get(outerOrderNo);
                List<String> deliveryNoList = logisticsList.stream()
                        .map(MroLogistics::getDeliveryNo)
                        .collect(Collectors.toList());
                mroLogisticsMapper.bitchUpdateMroLogisticsStatus(deliveryNoList, 2,nickName);
            }
        }
    }

    @Override
    public void adjustPoint(List<String> outerOrderNos) {
        if (CollectionUtils.isEmpty(outerOrderNos)) {
            throw new BadRequestException("订单编号不能为空！");
        }
        //判断订单状态 ：已完成时添加积分
        List<OrderInfo> orderInfoList = orderInfoMapper.selectOrderInfoByOuterOrderNos(outerOrderNos);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应订单数据");
        }
        orderInfoList.forEach(item -> {
            if (item.getStatus() != 4) {
                throw new BadRequestException("订单编号为：" + item.getOuterOrderNo() + "的状态非 已完成 ,不可添加积分！");
            }
        });

        for (OrderInfo orderInfo : orderInfoList) {
            AdjustPointVo adjustPointVo = new AdjustPointVo();
            adjustPointVo.setRequestId(orderInfo.getOuterOrderNo());
            adjustPointVo.setRequestType(String.valueOf(0));//请求类型 :0-其他

            ArrayList<AdjustPointVo.AdjustPointInfo> AdjustPointInfoList = new ArrayList<>();
            //一个订单一个客户
            AdjustPointInfoList.add(new AdjustPointVo.AdjustPointInfo(6017037364631L,orderInfo.getWid()));
            adjustPointVo.setAdjustPointInfoList(AdjustPointInfoList);

            adjustPointVo.setChangePoint(orderInfo.getRemark2());//积分数值
            adjustPointVo.setAdjustType(String.valueOf(1));//积分的调整类型:1-调增；2-调减
            adjustPointVo.setChangeReason("代客下单完成时添加对应积分");//积分变更原因
            adjustPointVo.setChangeType(String.valueOf(109));//变更类型:109-其他

            //调用微盟 调整积分
            boolean success = weimobUtil.adjustPointToWeimob(adjustPointVo);
        }
    }
    @Override
    public void sendCancelStatus(List<String> outerOrderNos) {
        if (CollectionUtils.isEmpty(outerOrderNos)) {
            throw new BadRequestException("订单编号不能为空！");
        }
        List<OrderInfo> orderInfoList = orderInfoMapper.selectOrderInfoByOuterOrderNos(outerOrderNos);
        if (CollectionUtils.isEmpty(orderInfoList)) {
            throw new BadRequestException("订单编号为：" + outerOrderNos + "找不到对应数据");
        }
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        String nickName = sysUser.getNickName();

        for (OrderInfo target : orderInfoList) {
            String outerOrderNo = target.getOuterOrderNo();
            if (!target.getCreateBy().equals(nickName)) {
                throw new BadRequestException("订单 " + outerOrderNo + " 当前登录人不是创建人，无法操作！");
            }
            if( ! target.getStatus().equals(2)){
                throw new BadRequestException("订单 " + outerOrderNo + " 的状态非【生效已发送】，无法操作");
            }
            if (ObjectUtils.isEmpty(target.getRemark5())) {
                throw new BadRequestException("订单 " + outerOrderNo + " 微盟平台订单编号为空,请检查！");
            }
            // 构建取消请求对象
            /*CancelOrderInfoVo cancelOrderInfoVo = new CancelOrderInfoVo();
            cancelOrderInfoVo.setOrderNo(target.getRemark5());
            cancelOrderInfoVo.setOrderStatus(9);
            CancelOrderInfoVo.CancelInfo cancelInfo = new CancelOrderInfoVo.CancelInfo();
            cancelInfo.setCancelType(2);
            cancelInfo.setReason("代客下单，订单取消");
            cancelInfo.setSpecialReason("代客下单,订单取消");
            cancelOrderInfoVo.setCancelInfo(cancelInfo);

            long currentTimeMillis = System.currentTimeMillis();
            List<CancelOrderInfoVo.OrderTimeInfo> orderTimeInfos = Arrays.asList(
                    new CancelOrderInfoVo.OrderTimeInfo(101, target.getCreateTime().getTime()),
                    new CancelOrderInfoVo.OrderTimeInfo(102, currentTimeMillis),
                    new CancelOrderInfoVo.OrderTimeInfo(103, currentTimeMillis),
                    new CancelOrderInfoVo.OrderTimeInfo(104, currentTimeMillis),
                    new CancelOrderInfoVo.OrderTimeInfo(105, currentTimeMillis),
                    new CancelOrderInfoVo.OrderTimeInfo(106, currentTimeMillis),
                    new CancelOrderInfoVo.OrderTimeInfo(107, currentTimeMillis),
                    new CancelOrderInfoVo.OrderTimeInfo(108, currentTimeMillis)
            );
            cancelOrderInfoVo.setOrderTimeInfos(orderTimeInfos);

            // 调用微盟取消接口
            boolean flag = weimobUtil.sendCancelInfoToWeimob(cancelOrderInfoVo);
            // 更新订单状态为 5-取消
            orderInfoMapper.updateOrderStatus(outerOrderNo, 5, nickName);*/

            //设置需要恢复的状态
            if(ObjectUtils.isEmpty(target.getStatus())){
                throw new BadRequestException("作废前状态为null,请检查");
            }
            orderInfoMapper.updateRestoreStatus(outerOrderNo, target.getStatus());
            orderInfoMapper.updateOrderStatus(outerOrderNo, 5,nickName);
        }
    }

    @Override
    public Long searchOrderInfoFromWeimob(String outerOrderNo, Long startTime, Long endTime) {
        if (StringUtils.isEmpty(outerOrderNo)) {
            throw new BadRequestException("代客订单编号不能为空！");
        }
        SearchOrderInfoVo searchOrderInfoVo = new SearchOrderInfoVo();
        searchOrderInfoVo.setPageNum(1);
        searchOrderInfoVo.setPageSize(50);
        SearchOrderInfoVo.QueryParameter queryParameter = new SearchOrderInfoVo.QueryParameter();
        queryParameter.setProcessVids(Arrays.asList(6017037364631L));
        queryParameter.setSearchType(18);
        queryParameter.setKeyword(outerOrderNo);
        SearchOrderInfoVo.QueryTime queryTime = new SearchOrderInfoVo.QueryTime();
        queryTime.setStartTime(startTime);
        queryTime.setEndTime(endTime);
        queryTime.setType(0);
        queryParameter.setQueryTime(queryTime);
        searchOrderInfoVo.setQueryParameter(queryParameter);

        //调用微盟 查询订单列表获取微盟订单编号
        Long orderNo = weimobUtil.searchOrderInfoFromWeimob(searchOrderInfoVo);
        return orderNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<OrderInfo> autoFinshedOrder(LocalDateTime expireTime) {
        // 查询待完成订单
        List<OrderInfo> autoFinishedOrderInofList = orderInfoMapper.autoFinshedOrderList(expireTime);
        if (CollectionUtils.isEmpty(autoFinishedOrderInofList)) {
            log.info("没有需要自动完成的订单");
            return Collections.emptyList();
        }
        // 获取全部外部订单号
        List<String> outerOrderNoList = autoFinishedOrderInofList.stream()
                .map(OrderInfo::getOuterOrderNo)
                .collect(Collectors.toList());
        // 查询物流信息
        List<MroLogistics> mroLogistics = mroLogisticsMapper.selectMroLogisticsByOuterOrderNo(outerOrderNoList);

        Map<String, List<MroLogistics>> mroLogisticMap = mroLogistics.stream()
                .collect(Collectors.groupingBy(MroLogistics::getOuterOrderNo));

        Map<String, Long> createTimeMap = autoFinishedOrderInofList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getCreateTime().getTime()
                ));

        List<OrderInfo> successList = new ArrayList<>();
        List<OrderInfo> failList = new ArrayList<>();
        for (OrderInfo orderInfo : autoFinishedOrderInofList) {
            try {
                processSingleOrder(orderInfo, mroLogisticMap, createTimeMap);
                successList.add(orderInfo);
            } catch (Exception e) {
                failList.add(orderInfo);
                log.error("【自动完成订单失败】outerOrderNo={}，错误原因：{}",
                        orderInfo.getOuterOrderNo(), e.getMessage(), e);
            }
        }
        log.info("自动完成订单任务结束，总数：{}，成功：{}，失败：{}",
                autoFinishedOrderInofList.size(), successList.size(), failList.size());
        if (!failList.isEmpty()) {
            log.info("失败订单列表：{}", failList);
        }
        return successList;
    }

    /**
     * 处理单个订单
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void processSingleOrder(OrderInfo orderInfo,
                                   Map<String, List<MroLogistics>> mroLogisticMap,
                                   Map<String, Long> createTimeMap) {
        //1、更新 微盟状态为完成
        SendFinishStatusVo sendFinishStatusVo = new SendFinishStatusVo();
        String outerOrderNo = orderInfo.getOuterOrderNo();
        Long orderNo = mroLogisticMap.get(outerOrderNo).get(0).getOrderNo();
        sendFinishStatusVo.setOrderNo(orderNo);
        sendFinishStatusVo.setOrderStatus(8);//完成

        List<SendFinishStatusVo.OrderTimeInfo> orderTimeInfos = new ArrayList<>();
        //101-订单创建时间；102-支付完成时间；103-可发货时间；104-订单首次发货时间；105-发货完成时间；106-确认收货时间；107-订单完成时间；108-订单取消时间
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(101, createTimeMap.get(outerOrderNo)));
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(102, createTimeMap.get(outerOrderNo)));
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(103, createTimeMap.get(outerOrderNo)));
        long currentTimeMillis = System.currentTimeMillis();
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(104, currentTimeMillis));
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(105, currentTimeMillis));
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(106, currentTimeMillis));
        orderTimeInfos.add(new SendFinishStatusVo.OrderTimeInfo(107, currentTimeMillis));
        sendFinishStatusVo.setOrderTimeInfos(orderTimeInfos);
        //调用微盟 外部订单更新
        boolean success = weimobUtil.sendFinishStatusToWeimob(sendFinishStatusVo);

        //2、(1)更新物流状态：2已完成  (2)  更新订单状态：4完成  (3)添加积分
        if (success) {
            String nickName = "system";
            /*try {
                String username = SecurityUtils.getUsername();
                if (StringUtils.isNotEmpty(username)) {
                    SysUser sysUser = sysUserMapper.selectUserByUserName(username);
                    if (sysUser != null && StringUtils.isNotEmpty(sysUser.getNickName())) {
                        nickName = sysUser.getNickName();
                    }
                }
            } catch (Exception e) {
                log.warn("获取当前登录用户昵称失败，使用默认昵称：{}", nickName, e);
            }*/
            orderInfoMapper.updateOrderStatus(outerOrderNo, 4,nickName);
            List<MroLogistics> logisticsList = mroLogisticMap.get(outerOrderNo);
            List<String> deliveryNoList = logisticsList.stream()
                    .map(MroLogistics::getDeliveryNo)
                    .collect(Collectors.toList());
            mroLogisticsMapper.bitchUpdateMroLogisticsStatus(deliveryNoList, 2,nickName);


            //3、调整微盟积分
            AdjustPointVo adjustPointVo = new AdjustPointVo();
            adjustPointVo.setRequestId(orderInfo.getOuterOrderNo());
            adjustPointVo.setRequestType(String.valueOf(0));//请求类型 :0-其他

            ArrayList<AdjustPointVo.AdjustPointInfo> AdjustPointInfoList = new ArrayList<>();
            //一个订单一个客户
            AdjustPointInfoList.add(new AdjustPointVo.AdjustPointInfo(6017037364631L,orderInfo.getWid()));
            adjustPointVo.setAdjustPointInfoList(AdjustPointInfoList);

            adjustPointVo.setChangePoint(orderInfo.getRemark2());//积分数值
            adjustPointVo.setAdjustType(String.valueOf(1));//积分的调整类型:1-调增；2-调减
            adjustPointVo.setChangeReason("代客下单完成时添加对应积分");//积分变更原因
            adjustPointVo.setChangeType(String.valueOf(109));//变更类型:109-其他
            //调用微盟 调整积分
            boolean adjustPointSuccess = weimobUtil.adjustPointToWeimob(adjustPointVo);
            if (!adjustPointSuccess) {
                log.warn("【积分调整失败】outerOrderNo={}", outerOrderNo);
            }
        }else {
            throw new RuntimeException("自动更新订单状态失败！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void restoreStatus(List<String> outerOrderNos) {
        if (CollectionUtils.isEmpty(outerOrderNos)) {
            throw new BadRequestException("订单编号不能为空！");
        }
        List<OrderInfo> orderInfoList = orderInfoMapper.selectOrderInfoByOuterOrderNos(outerOrderNos);

        Map<String, Integer> statusMap = orderInfoList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getStatus()
                ));
        SysUser sysUser = sysUserMapper.selectUserByUserName(SecurityUtils.getUsername());
        String nickName = sysUser.getNickName();
        Map<String, String> createByMap = orderInfoList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getCreateBy()
                ));
        for (String outerOrderNo : outerOrderNos) {
            Integer status = statusMap.get(outerOrderNo);
            if(status!=6){
                throw new BadRequestException("订单编号为"+outerOrderNo+"非【删除】状态，不可【恢复】");
            }
            if(!createByMap.get(outerOrderNo).equals(nickName)  ){
                throw new BadRequestException("【当前登录人】不等于【订单创建人】，不可【恢复】");
            }
        }
        Map<String, Integer> restoreStatusMap = orderInfoList.stream()
                .collect(Collectors.toMap(
                        OrderInfo::getOuterOrderNo,
                        order -> order.getRestoreStatus()
                ));
        for (String outerOrderNo : outerOrderNos) {
            Integer restoreStatus = restoreStatusMap.get(outerOrderNo);
            if(restoreStatus==null){
                throw new BadRequestException("作废前的状态为null，请检查！");
            }
            orderInfoMapper.updateOrderStatus(outerOrderNo, restoreStatus,nickName);
            //清空需要恢复的状态
            orderInfoMapper.updateRestoreStatus(outerOrderNo, null);
        }
    }
}
